//////////////////////////////////////////////////////////////////////////////
// DCTO8DMAIN.C - dcto8d emulator main program
// Author   : Daniel Coulom - danielcoulom@gmail.com
// Web site : http://dcto8.free.fr
// Pandora port : Sylvain FABRE
//
// This file is part of DCTO8D.
//
// DCTO8D is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// DCTO8D is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with DCTO8D. If not, see <http://www.gnu.org/licenses/>.
//
//////////////////////////////////////////////////////////////////////////////

#include <SDL.h>
#include <SDL_ttf.h>
#include "dcto8dicon.h"
#include "dcto8dglobal.h"
#include "dcto8dmsg.h"
#include "dcto8dinterface.h"

#define SDL_main main    //indispensable pour �viter l'erreur
                         //undefined reference to `WinMain@16'


// global variables //////////////////////////////////////////////////////////
const SDL_VideoInfo *videoinfo;
TTF_Font  *globfont  = NULL;
SDL_AudioSpec audio;
SDL_AudioSpec audio_obtained;

unsigned char cursor[] __attribute__ ((aligned (8))) = {
 128,0,192,0,160,0,144,0,136,0,132,0,130,0,129,0,128,128,128,64,128,32,129,240,
 137,0,152,128,164,128,196,64,130,64,2,32,1,32,1,16,0,176,0,192,0,0,0,0,128,0,
 192,0,224,0,240,0,248,0,252,0,254,0,255,0,255,128,255,192,255,224,255,240,255,
 0,231,128,199,128,131,192,3,192,3,224,1,224,1,240,0,240,0,192,0,0,0,0};

extern int language;

extern void Createdialogbox(int x, int y);
extern void Drawmessagebox(char *titre, char *text1[], char *text2[]);

// About message box /////////////////////////////////////////////////////////
void About()
{
 int i;
 char *text1[9], *text2[6];
 Createdialogbox(336, 236);
 for(i = 0; i < 8; i++) text1[i] = msg[i + 2][language]; text1[i] = "";
 text1[i] = "";
 for(i = 0; i < 5; i++) text2[i] = msg[i + 20][language]; text2[i] = "";

 Drawmessagebox(msg[1][language], text1, text2);

}

// Message d'erreur SDL //////////////////////////////////////////////////////
void SDL_error(int n)
{
 char string[256];
 char *text1[3], *text2[1];
 Createdialogbox(300, 90);
 sprintf(string, "%i", n);
 text1[0] = string;
 text1[1] = SDL_GetError();
 text1[2] = "";
 text2[0] = "";
 Drawmessagebox("SDL error", text1, text2);
 SDL_Delay(1000);
}

// Message d'erreur emulateur ////////////////////////////////////////////////
void Erreur(int n)
{
 char string[256];
 char *text1[3], *text2[1];
 Createdialogbox(300, 90);
 sprintf(string, "%i", n);
 text1[0] = string;
 text1[1] = msg[n][language];
 text1[2] = "";
 text2[0] = "";
 Drawmessagebox(msg[10][language], text1, text2);
}

// Affichage de controle d'une valeur ///////////////////////////////////////
void Info(int n)
{
 char string[32];
 char *text1[4], *text2[1];
 sprintf(string, "0x%04x (%i)", n, n);
 Createdialogbox(120, 60);
 text1[0] = string;
 text1[1] = "";
 text2[0] = "";
 Drawmessagebox("Info", text1, text2);
}

// Joysticks initialization //////////////////////////////////////////////////
void Joyinit()
{
 //int i = 0;
 //if(joySetCapture(hwndmain, JOYSTICKID1, 0, TRUE)) i += 1;
 //if(joySetCapture(hwndmain, JOYSTICKID2, 0, TRUE)) i += 2;
 //joySetThreshold(JOYSTICKID1, 2000); //10 trop peu pour Trust Predator
 //joySetThreshold(JOYSTICKID2, 2000); //2000 semble correct
}

// Play sound ////////////////////////////////////////////////////////////////
void Playsound(void *udata, Uint8 *stream, int bufferlength)
{
  int i;
  int mcycles; //nombre de milliemes de cycles entre deux echantillons
  int icycles; //nombre entier de cycles entre deux echantillons
  extern int frequency; //frequence 6809 en kHz

  //45 cycles 6809 a 992250 Hz = un echantillon a 22050 Hz
  for(i = 0; i < bufferlength; i+=2)
  {
    if(psys->pause6809) {stream[i+0] = 128; stream[i+1] = 128; continue;}
    //calcul et execution du nombre de cycles entre deux echantillons
    //nbre de cycles theoriques pour la periode en cours =
    //nbre theorique + relicat arrondi precedent - cycles en trop precedent
    mcycles = frequency * 100000 / 2205;   //milliemes de cycles theoriques
    mcycles += psys->report;                     //milliemes de cycles corriges
    icycles = mcycles / 1000;              //nbre entier de cycles a effectuer
    psys->report = mcycles - 1000 * icycles;     //relicat de l'arrondi a reporter
    psys->report -= 1000 * Run(icycles);         //retrancher les milliemes en trop
    stream[i+0] = (psys->mute) ? 128 : psys->sound + 96;
    stream[i+1] = (psys->mute) ? 128 : psys->sound + 96;
  }
  if ( psys->globforcerefresh == 1)
  {
    Displayscreen();
    psys->globforcerefresh = 0;
  }
}

//Event loop /////////////////////////////////////////////////////////////////
void Eventloop()
{
 SDL_Event event;
 extern dialogeditbox *focus;   //editbox ayant le focus
 extern int xclient, yclient, blink;
 extern int penbutton, xmouse, ymouse, xmove, ymove;
 extern void Resizescreen(int x, int y), Displayscreen();
 extern void Mouseclick(), Dialogmove();
 extern void Keydown(int sym, int scancode, int unicode);
 extern void Keyup(int sym, int scancode);

 while(1)
 {
  while(SDL_PollEvent(&event))
  {
   switch(event.type)
   {
    case SDL_VIDEORESIZE:
         Resizescreen(event.resize.w, event.resize.h); break;
    case SDL_MOUSEBUTTONDOWN:
         psys->penbutton = 1; Mouseclick(); break;
    case SDL_MOUSEBUTTONUP:
         psys->penbutton = 0; xmove = ymove = 0; break;
    case SDL_MOUSEMOTION:
         xmouse = event.motion.x; ymouse = event.motion.y;
         psys->xpen = xmouse * XBITMAP / xclient - 16;
         psys->ypen = (ymouse - YSTATUS) * YBITMAP / yclient - 8;
         if(xmove) if(ymove) Dialogmove(); break;
    case SDL_KEYDOWN:
         Keydown(event.key.keysym.sym, event.key.keysym.scancode,
                 event.key.keysym.unicode); break;
    case SDL_KEYUP:
         Keyup(event.key.keysym.sym, event.key.keysym.scancode); break;
    case SDL_QUIT: return;
   }
  }
  SDL_Delay(5); blink++;
  if(blink == 0) {if(focus != NULL) Draweditbox(focus);}
  if(blink > 20) {blink = -20; if(focus != NULL) Draweditbox(focus);}
 }
}

/* Some external stuff, ugly */
extern int xclient, yclient, screencount;
extern void Init6809(), Initfilenames(), Hardreset();
extern void Initoptions(), Saveoptions();
extern void Initbuttonsurfaces(), Initstatusbar();
extern void Resizescreen(int x, int y), Displayscreen(), Keyboardinit();

//Main program ///////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
  SDL_RWops *rw;

  /* Font init section */
  if(TTF_Init()==-1) {
    printf("TTF_Init: Error \n");
    exit(0);
  }
  globfont = TTF_OpenFont("arial.ttf", 10);
  if ( globfont == NULL ) {
    printf("TTF_OpenFont: Error \n");
    exit(0);
  }

  psys->globforcerefresh = 0;

  /* initialisations*/
  Joyinit();                        //Joysticks initialization
  Initoptions();                    //Option initialization
  Initfilenames();
  Init6809();
  Keyboardinit();                   //Keyboard initialization
  Hardreset();                      //MO5 initialization

  /* Initialize SDL video and keyboard */
  if(SDL_Init(SDL_INIT_VIDEO) < 0) SDL_error(2);
  atexit(TTF_Quit);
  atexit(SDL_Quit);
  rw = SDL_RWFromMem(dcto8dicon, sizeof(dcto8dicon));
  SDL_WM_SetIcon(SDL_LoadBMP_RW(rw, 1), NULL);  //icone fenetre
  SDL_WM_SetCaption(msg[0][language], NULL);    //titre fenetre
  SDL_SetCursor(SDL_CreateCursor(cursor, cursor + 48, 16, 24, 0, 0)); //curseur
  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
  Resizescreen(xclient, yclient + YSTATUS);
  Initbuttonsurfaces(); //Initialisation des surfaces des boutons
  Initstatusbar();      //Initialisation de la surface de la barre de statut
  screencount = 0;
  Displayscreen();

 //initialize SDL audio
 if(SDL_Init(SDL_INIT_AUDIO) < 0) SDL_error(3);
 audio.freq = 22050;
 audio.format = AUDIO_U8;
 audio.channels = 2;
 audio.samples = 2048;
 audio.callback = Playsound;
 audio.userdata = NULL;
 if(SDL_OpenAudio(&audio, &audio_obtained) < 0 ) SDL_error(4);
 //printf("Audio obtained : %d - %d - %d - %d \n", audio_obtained.freq, audio_obtained.format, audio_obtained.channels, audio_obtained.samples );
 SDL_PauseAudio(0);    //Lance l'emulation
 SDL_EnableUNICODE(1);

 //test events
 Eventloop();

 //quit
 psys->pause6809 = 1;
 SDL_PauseAudio(1);
 Saveoptions();
 SDL_Delay(100);
 SDL_Quit();
 return 0;
}
